//This file explains the form of machine learning parameters
package main

import "fmt"

//TrainingParameters is the metadata of a model
type TrainingParameters struct {
	Weight [][]float64 `json:"layer.weight"`
	Bias   []float64   `json:"layer.bias"`
}

//AverageHandler is called by Aggregator to average TrainingParameters of several local models into TrainingParameters of single global model.
//Current averaging method is: arithmetic average.
func AverageHandler(dSet []*TrainingParameters) (*TrainingParameters,error) {
	if len(dSet) == 0 || dSet == nil {
		return nil,fmt.Errorf("cannot average empty data")
	}

	//add all TrainingParameters
	d := new(TrainingParameters)
	*d = *dSet[0]
	dSetLen := len(dSet)
	for i := 1; i < dSetLen; i++ {
		for k, bia := range dSet[i].Bias {
			d.Bias[k] += bia
		}
		for k, f := range dSet[i].Weight {
			for kk, ff := range f {
				d.Weight[k][kk] += ff
			}
		}
	}
	//average
	for i := range d.Bias {
		d.Bias[i] = d.Bias[i] / float64(dSetLen)
	}
	for i := range d.Weight {
		for i2 := range d.Weight[i] {
			d.Weight[i][i2] /= float64(dSetLen)
		}
	}

	return d,nil
}
